home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / gag / AlertPicture.lha / jiff_load.c < prev    next >
C/C++ Source or Header  |  1992-09-02  |  8KB  |  298 lines

  1. /**********************************************************************
  2. *
  3. *            jiff.c   Jim Kent's iff - ilbm  reader
  4. *
  5. * This is the (sortof) short (sortof) simple no-frills IFF reader
  6. * to get something out of DPaint, Images, or the Animator.  It
  7. * works well with the Aztec C compiler.  It should work with Lattice
  8. * but you never know until you try it.  I haven't.
  9. *
  10. * I've included a simple main program.  This is just to make it
  11. * stand alone.  Since amiga screen initializations are massive, all
  12. * it does as is is read it into a BitMap, and then free up the BitMap.
  13. * Should crash it if it's gonna crash though.
  14. *
  15. * The main interface to this is through the routine read_iff(filename).
  16. * This returns a ILBM_info structure-pointer on success, and NULL on
  17. * failure.  It cleans up after itself on failure.
  18. *
  19. * I hope you will find this useful and easy to use.  Please forgive
  20. * my funky indentation style?  Well at least I'm consistent!
  21. *
  22. * To demonstrate what a nice guy I am even though I'm far from wild
  23. * about the IFF standard I'm placing this in the public domain.  When
  24. * you remove the DEBUG and PARANOID definitions the code is only
  25. * 1536 bytes long.
  26. *
  27. *        -Jim Kent  April 22, 1986
  28. *
  29. * Restructured for error messages where paranoid.
  30. *
  31. *     -Tim Ferguson, Alchemy Software Development.  June 14, 1993
  32. ************************************************************************/
  33.  
  34. #include <stdio.h>
  35. #include <exec/types.h>
  36. #include <exec/memory.h>
  37. #include <graphics/gfx.h>
  38. #include <libraries/dos.h>
  39. #include "jiff.h"
  40.  
  41. char iff_err_msg_read[80], iff_warn_msg_read[80];
  42.  
  43. static struct ILBM_info *read_body(FILE *, register struct ILBM_info *, long);
  44. static struct ILBM_info *read_ilbm(FILE *, struct ILBM_info *, long, short);
  45.  
  46.  
  47. /* --------------------------------------------------------------------- */
  48. struct ILBM_info *read_iff(char *name, struct ILBM_info *info, short just_colors)
  49. {
  50. FILE *file;
  51. struct form_chunk chunk;
  52.  
  53.     if((file = fopen(name, "r") ) == 0)
  54.         {
  55.         sprintf(iff_err_msg_read, "Couldn't Open %s to read.\n", name);
  56.         return(NULL);
  57.         }
  58.  
  59.     if(fread(&chunk, sizeof(struct form_chunk), 1, file) != 1)
  60.         {
  61.         sprintf(iff_err_msg_read, "ILBM truncated at 1\n");
  62.         fclose(file);
  63.         return(NULL);
  64.         }
  65.  
  66.     if(chunk.fc_type.b4_type != FORM)
  67.         {
  68.         sprintf(iff_err_msg_read, "Not a FORM - %s\n", name);
  69.         fclose(file);
  70.         return(NULL);
  71.         }
  72.  
  73.     if(chunk.fc_subtype.b4_type != ILBM)
  74.         {
  75.         sprintf(iff_err_msg_read, "FORM not an ILBM - %s\n", name);
  76.         fclose(file);
  77.         return(NULL);
  78.         }
  79.  
  80.     info = read_ilbm(file, info, chunk.fc_length - sizeof(chunk), just_colors);
  81.     fclose(file);
  82.     return(info);
  83. }
  84.  
  85.  
  86. /* --------------------------------------------------------------------- */
  87. static struct ILBM_info *read_ilbm(FILE *file, struct ILBM_info *info, long length, short just_colors)
  88. {
  89. struct iff_chunk chunk;
  90. int i;
  91. long read_in = 0;
  92. int got_header = FALSE;  /*to make sure gots the header first*/
  93. int got_cmap = FALSE;  /*make sure get cmap before "BODY" */
  94.  
  95. /* make sure the Planes are all NULL so can free up memory easily
  96.   on error abort */
  97.     for(i = 0; i < 8; i++) info->bitmap.Planes[i] = NULL;
  98.  
  99.     while(read_in < length)
  100.         {
  101.         if(fread(&chunk, sizeof(chunk), 1, file) != 1)
  102.             {
  103.             sprintf(iff_err_msg_read, "ILBM truncated at 1\n");
  104.             return(NULL);
  105.             }
  106.  
  107.         switch (chunk.iff_type.b4_type)
  108.             {
  109.             case BMHD:
  110.                 if(fread(&info->header, sizeof(info->header), 1, file) != 1)
  111.                     {
  112.                     sprintf(iff_err_msg_read, "ILBM truncated at 2\n");
  113.                     return(NULL);
  114.                     }
  115.  
  116.                 got_header = TRUE;
  117.                 break;
  118.  
  119.             case CMAP:
  120.                 if(!got_header)
  121.                     {
  122.                     sprintf(iff_err_msg_read, "CMAP before BMHD\n");
  123.                     return(NULL);
  124.                     }
  125.  
  126.                 if(chunk.iff_length <= 3*MAXCOL )
  127.                     {
  128.                     if(fread(info->cmap, (int)chunk.iff_length, 1, file) != 1)
  129.                         {
  130.                         sprintf(iff_err_msg_read, "ILBM truncated at 3\n");
  131.                         return(NULL);
  132.                         }
  133.                     }
  134.                 else
  135.                     {
  136.                     sprintf(iff_err_msg_read, "warning, more than %d colors in ILBM CMAP\n", MAXCOL);
  137.                     if(fread(info->cmap, 3*MAXCOL, 1, file) != 1)
  138.                         {
  139.                         sprintf(iff_err_msg_read, "ILBM truncated at 4\n");
  140.                         return(NULL);
  141.                         }
  142.                     bit_bucket(file, chunk.iff_length - sizeof(3*MAXCOL));
  143.                     }
  144.                 got_cmap = TRUE;
  145.  
  146.                 if(just_colors) return(info);
  147.                 break;
  148.  
  149.             case BODY:
  150.                 if(!got_cmap)
  151.                     {
  152.                     sprintf(iff_err_msg_read, "BODY before CMAP\n");
  153.                     return(NULL);
  154.                     }
  155.                 return(read_body(file, info, chunk.iff_length));
  156.  
  157.             default:    /*squawk about unknown types if PARANOID */
  158.                 sprintf(iff_warn_msg_read, "unknown type %lx of b4_type\n", chunk.iff_type.b4_type);
  159.  
  160.             case GRAB:  /*ignore documented but unwanted types*/
  161.             case DEST:
  162.             case SPRT:
  163.             case CAMG:
  164.             case CRNG:
  165.             case CCRT:
  166.                 bit_bucket(file, chunk.iff_length);
  167.                 break;
  168.             }
  169.  
  170.         read_in += chunk.iff_length + sizeof(chunk);
  171.         }
  172.  
  173.     sprintf(iff_err_msg_read, "No BODY in ILBM\n");
  174.     return(NULL); 
  175. }
  176.  
  177.  
  178. /* --------------------------------------------------------------------- */
  179. static struct ILBM_info *read_body(FILE *file, register struct ILBM_info *info, long length)
  180. {
  181. struct ILBM_header *header;
  182. struct BitMap *bm;
  183. int i, j;
  184. int rlength;
  185. int plane_offset;
  186.  
  187.     if(info->header.nPlanes > 8)
  188.         {
  189.         sprintf(iff_err_msg_read, "IFF %d planes is too large.  Maximum planes is 8\n",
  190.             info->header.nPlanes);
  191.         return(NULL);
  192.         }
  193.  
  194. /* ok a little more error checking */
  195.     if(info->header.compression != 0 && info->header.compression != 1)
  196.         {
  197.         sprintf(iff_err_msg_read, "unrecognized compression type %d\n", info->header.compression);
  198.         return(NULL);
  199.         }
  200.  
  201. /*set up the bitmap part that doesn't involve memory allocation first -
  202.   hey this part does get done, and let's be optimistic...*/
  203.  
  204.     info->bitmap.BytesPerRow = line_bytes(info->header.w);
  205.     info->bitmap.Rows = info->header.h;
  206.     info->bitmap.Depth = info->header.nPlanes;
  207.     info->bitmap.Flags = info->bitmap.pad = 0;
  208.  
  209.     rlength = info->bitmap.Rows * info->bitmap.BytesPerRow;
  210.  
  211.     for(i=0; i<info->header.nPlanes; i++)
  212.         {
  213.         if((info->bitmap.Planes[i] = ralloc(rlength)) == NULL)
  214.             {
  215.             sprintf(iff_err_msg_read, "couldn't alloc plane %d in read_body\n",i);
  216.             free_planes( &info->bitmap );
  217.             return(NULL);
  218.             }
  219.         }
  220.  
  221.     plane_offset = 0;
  222.     for(i=0; i<info->bitmap.Rows; i++)
  223.         {
  224.     /* this test should be in the inner loop for shortest code,
  225.        in the outer loop for greatest speed, so sue me I compromised */
  226.         if(info->header.compression == 0)
  227.             {
  228.             for(j = 0; j < info->bitmap.Depth; j++)
  229.                 {
  230.                 if(fread(info->bitmap.Planes[j] + plane_offset,
  231.                     info->bitmap.BytesPerRow, 1, file) != 1)
  232.                     {
  233.                     sprintf(iff_err_msg_read, "ILBM truncated at 6\n");
  234.                     free_planes(&info->bitmap);
  235.                     return(NULL);
  236.                     }
  237.                 }
  238.             }
  239.         else
  240.             {
  241.             register char *dest, value;
  242.             register int so_far, count;  /*how much have unpacked so far*/
  243.  
  244.             for(j = 0; j < info->bitmap.Depth; j++)
  245.                 {
  246.                 so_far = info->bitmap.BytesPerRow;
  247.                 dest = (char *)info->bitmap.Planes[j] + plane_offset;
  248.                 while(so_far > 0)
  249.                     {
  250.                     if((value = getc(file)) == 128);
  251.                     else if(value > 0)
  252.                         {
  253.                         count = (int)value + 1;
  254.                         so_far -= count;
  255.                         if(fread(dest, count, 1, file) != 1)
  256.                             {
  257.                             sprintf(iff_err_msg_read, "ILBM truncated at 7\n");
  258.                             free_planes(&info->bitmap);
  259.                             return(NULL);
  260.                             }
  261.                         dest += count;
  262.                         }
  263.                     else 
  264.                         {
  265.                         count = (int)-value + 1;
  266.                         so_far -= count;
  267.                         value = getc(file);
  268.                         while(--count >= 0)  /*this is fastest loop in C */
  269.                             *dest++ = value;
  270.                         }
  271.                     }
  272.                 if(so_far != 0)
  273.                     {
  274.                     sprintf(iff_err_msg_read, "compression quite screwed up, aborting %d\n", so_far);
  275.                     free_planes(&info->bitmap);
  276.                     return(NULL);
  277.                     }
  278.                 }
  279.             }
  280.         plane_offset += info->bitmap.BytesPerRow;
  281.         }
  282.     return(info);
  283. }
  284.  
  285.  
  286. /* --------------------------------------------------------------------- */
  287. void free_planes(register struct BitMap *bmap)
  288. {
  289. PLANEPTR plane;
  290. long length;
  291. short i;
  292.  
  293.     length = bmap->BytesPerRow * bmap->Rows;
  294.  
  295.     for(i = 0; i < 8; i++)
  296.         if((plane = bmap->Planes[i]) != NULL) rfree(plane, length);
  297. }
  298.